"""
API response models following SOLID principles.
"""

from typing import Any, Dict, Optional, Generic, TypeVar, List
from datetime import datetime
from pydantic import BaseModel, Field

T = TypeVar('T')


class APIResponse(BaseModel, Generic[T]):
    """Base API response model."""
    
    success: bool = Field(description="Whether the request was successful")
    message: str = Field(description="Response message")
    data: Optional[T] = Field(default=None, description="Response data")
    timestamp: datetime = Field(default_factory=datetime.utcnow, description="Response timestamp")
    request_id: Optional[str] = Field(default=None, description="Request ID for tracking")


class SuccessResponse(APIResponse[T]):
    """Success response model."""
    
    success: bool = Field(default=True, description="Success flag")
    
    @classmethod
    def create(
        cls,
        data: T,
        message: str = "Success",
        request_id: Optional[str] = None
    ) -> 'SuccessResponse[T]':
        """Create success response."""
        return cls(
            success=True,
            message=message,
            data=data,
            request_id=request_id
        )


class ErrorResponse(APIResponse[None]):
    """Error response model."""
    
    success: bool = Field(default=False, description="Success flag")
    error_code: Optional[str] = Field(default=None, description="Error code")
    error_details: Optional[Dict[str, Any]] = Field(default=None, description="Error details")
    
    @classmethod
    def create(
        cls,
        message: str,
        error_code: Optional[str] = None,
        error_details: Optional[Dict[str, Any]] = None,
        request_id: Optional[str] = None
    ) -> 'ErrorResponse':
        """Create error response."""
        return cls(
            success=False,
            message=message,
            error_code=error_code,
            error_details=error_details,
            request_id=request_id
        )


class PaginatedResponse(BaseModel, Generic[T]):
    """Paginated response model."""
    
    items: List[T] = Field(description="List of items")
    total: int = Field(description="Total number of items")
    page: int = Field(description="Current page number")
    size: int = Field(description="Page size")
    pages: int = Field(description="Total number of pages")
    has_next: bool = Field(description="Whether there is a next page")
    has_prev: bool = Field(description="Whether there is a previous page")


class ListResponse(SuccessResponse[List[T]]):
    """List response model."""
    
    count: int = Field(description="Number of items in the list")
    
    @classmethod
    def create(
        cls,
        items: List[T],
        message: str = "Success",
        request_id: Optional[str] = None
    ) -> 'ListResponse[T]':
        """Create list response."""
        return cls(
            success=True,
            message=message,
            data=items,
            count=len(items),
            request_id=request_id
        )


class CreatedResponse(SuccessResponse[T]):
    """Created resource response model."""
    
    @classmethod
    def create(
        cls,
        data: T,
        message: str = "Resource created successfully",
        request_id: Optional[str] = None
    ) -> 'CreatedResponse[T]':
        """Create created response."""
        return cls(
            success=True,
            message=message,
            data=data,
            request_id=request_id
        )


class UpdatedResponse(SuccessResponse[T]):
    """Updated resource response model."""
    
    @classmethod
    def create(
        cls,
        data: T,
        message: str = "Resource updated successfully",
        request_id: Optional[str] = None
    ) -> 'UpdatedResponse[T]':
        """Create updated response."""
        return cls(
            success=True,
            message=message,
            data=data,
            request_id=request_id
        )


class DeletedResponse(SuccessResponse[None]):
    """Deleted resource response model."""
    
    @classmethod
    def create(
        cls,
        message: str = "Resource deleted successfully",
        request_id: Optional[str] = None
    ) -> 'DeletedResponse':
        """Create deleted response."""
        return cls(
            success=True,
            message=message,
            data=None,
            request_id=request_id
        )


class HealthCheckResponse(BaseModel):
    """Health check response model."""
    
    status: str = Field(description="Service status")
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    version: Optional[str] = Field(default=None, description="Service version")
    uptime: Optional[float] = Field(default=None, description="Service uptime in seconds")
    dependencies: Optional[Dict[str, str]] = Field(default=None, description="Dependency status")


class MetricsResponse(BaseModel):
    """Metrics response model."""
    
    metrics: Dict[str, Any] = Field(description="Application metrics")
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    period: Optional[str] = Field(default=None, description="Metrics period")


class ValidationErrorDetail(BaseModel):
    """Validation error detail model."""
    
    field: str = Field(description="Field name")
    message: str = Field(description="Error message")
    value: Any = Field(description="Invalid value")


class ValidationErrorResponse(ErrorResponse):
    """Validation error response model."""
    
    validation_errors: List[ValidationErrorDetail] = Field(description="Validation errors")
    
    @classmethod
    def create(
        cls,
        validation_errors: List[ValidationErrorDetail],
        message: str = "Validation failed",
        request_id: Optional[str] = None
    ) -> 'ValidationErrorResponse':
        """Create validation error response."""
        return cls(
            success=False,
            message=message,
            error_code="VALIDATION_ERROR",
            validation_errors=validation_errors,
            request_id=request_id
        )